<!DOCTYPE html>
<html>
<head>
	<!-- Global site tag (gtag.js) - Google Analytics -->
	<script async src="https://www.googletagmanager.com/gtag/js?id='UA-133422980-2"></script>
	<script>
	  window.dataLayer = window.dataLayer || [];
	  function gtag(){dataLayer.push(arguments);}
	  gtag('js', new Date());

	  gtag('config', 'UA-133422980-2');
	</script>

	<meta charset="utf-8">
	<meta http-equiv="x-ua-compatible" content="ie=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1">

	<title>
		gem5: In port code blocks 
	</title>

	<!-- SITE FAVICON -->
	<link rel="shortcut icon" type="image/gif" href="/assets/img/gem5ColorVert.gif"/>

	<link rel="canonical" href="http://localhost:4000/documentation/learning_gem5/part3/cache-in-ports/">
	<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,700,800,600' rel='stylesheet' type='text/css'>
	<link href='https://fonts.googleapis.com/css?family=Muli:400,300' rel='stylesheet' type='text/css'>

	<!-- FAVICON -->
	<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">

	<!-- BOOTSTRAP -->
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">

	<!-- CUSTOM CSS -->
	<link rel="stylesheet" href="/css/main.css">
</head>


<body>
	<nav class="navbar navbar-expand-md navbar-light bg-light">
  <a class="navbar-brand" href="/">
		<img src="/assets/img/gem5ColorLong.gif" alt="gem5" height=55px>
	</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavDropdown">
    <!-- LIST FOR NAVBAR -->
    <ul class="navbar-nav ml-auto">
      <!-- HOME -->
      <li class="nav-item ">
        <a class="nav-link" href="/">Home</a>
      </li>

      <!-- ABOUT -->
			<li class="nav-item dropdown ">
				<a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
					About
				</a>
				<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
          <a class="dropdown-item" href="/about">About gem5</a>
          <a class="dropdown-item" href="/publications">Publications</a>
          <a class="dropdown-item" href="/governance">Governance</a>
				</div>
			</li>

      <!-- DOCUMENTATION -->
			<li class="nav-item dropdown active">
				<a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
					Documentation
				</a>
				<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
					<!-- Pull navigation from _data/documentation.yml -->
					
            <a class="dropdown-item" href="/documentation">gem5 documentation</a>
					
            <a class="dropdown-item" href="/documentation/learning_gem5/introduction">Learning gem5</a>
					
            <a class="dropdown-item" href="http://doxygen.gem5.org/release/current/index.html">gem5 Doxygen</a>
					
            <a class="dropdown-item" href="/documentation/reporting_problems">Reporting Problems</a>
					
				</div>
			</li>

      <!-- EVENTS -->
			<li class="nav-item dropdown ">
        <a class="nav-link" href="/events/">Events</a>
			</li>

      <!-- CONTRIBUTING -->
      <li class="nav-item ">
        <a class="nav-link" href="/contributing">Contributing</a>
      </li>

      <!-- BLOG -->
      <li class="nav-item ">
        <a class="nav-link" href="/blog">Blog</a>
      </li>

      <!-- SEARCH -->
			<li class="nav-item ">
        <a class="nav-link" href="/search">Search</a>
      </li>
    </ul>
  </div>
</nav>

	<main>
		<div class="sidenav-top">
  <div class="sidenav-brand bg-light">
    <a href="/"><img src="/assets/img/gem5ColorLong.gif" height="55px"></a>
  </div>
  <div class="search">
    <form action="/search" method="get">
      <!-- <label for="search-box"><i class="fa fa-search"></i></label> -->
      <input type="text" name="query">
      <button type="submit" name="submit"><i class="fa fa-search"></i></button>
    </form>
  </div>
</div>
<div class="sidenav">
  <!-- Pull navigation from _data/documentation.yml -->
  
    
  
    
    
      <a class="item" href="/documentation/learning_gem5/introduction" role="button" aria-expanded="false" aria-controls="collapseExample">
        Introduction
      </a>
      <div class="collapse " id="introduction">
        
      </div>
    
      <a class="item" data-toggle="collapse" href="#part1" role="button" aria-expanded="false" aria-controls="collapseExample">
        Getting Started
      </a>
      <div class="collapse " id="part1">
        
          <a class="subitem " href="/documentation/learning_gem5/part1/building">Building gem5</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part1/simple_config">Creating a simple configuration script</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part1/cache_config">Adding cache to configuration script</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part1/gem5_stats">Understanding gem5 statistics and output</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part1/example_configs">Using the default configuration scripts</a>
        
      </div>
    
      <a class="item" data-toggle="collapse" href="#part2" role="button" aria-expanded="false" aria-controls="collapseExample">
        Modifying/Extending
      </a>
      <div class="collapse " id="part2">
        
          <a class="subitem " href="/documentation/learning_gem5/part2/environment">Setting up your development environment</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/helloobject">Creating a very simple SimObject</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/debugging">Debugging gem5</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/events">Event-driven programming</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/parameters">Adding parameters to SimObjects and more events</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/memoryobject">Creating SimObjects in the memory system</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/simplecache">Creating a simple cache object</a>
        
      </div>
    
      <a class="item" data-toggle="collapse" href="#part3" role="button" aria-expanded="false" aria-controls="collapseExample">
        Modeling Cache Coherence with Ruby
      </a>
      <div class="collapse show" id="part3">
        
          <a class="subitem " href="/documentation/learning_gem5/part3/MSIintro">Introduction to Ruby</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/cache-intro">MSI example cache protocol</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/cache-declarations">Declaring a state machine</a>
        
          <a class="subitem active" href="/documentation/learning_gem5/part3/cache-in-ports">In port code blocks</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/cache-actions">Action code blocks</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/cache-transitions">Transition code blocks</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/directory">MSI Directory implementation</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/MSIbuilding">Compiling a SLICC protocol</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/configuration">Configuring a simple Ruby system</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/running">Running the simple Ruby system</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/MSIdebugging">Debugging SLICC Protocols</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/simple-MI_example">Configuring for a standard protocol</a>
        
      </div>
    
      <a class="item" href="/documentation/learning_gem5/gem5_101/" role="button" aria-expanded="false" aria-controls="collapseExample">
        gem5 101
      </a>
      <div class="collapse " id="gem5_101">
        
      </div>
    
    
  
    
  
    
  
</div>


<div class="container" id="doc-container">
  <div class="edit"><a href="https://gem5.googlesource.com/public/gem5-website/+/refs/heads/master/README.md">Edit this page</a></div>
  <b>authors:</b> Jason Lowe-Power<br>
  

  <br>
  <h1 id="in-port-code-blocks">In port code blocks</h1>

<p>After declaring all of the structures we need in the state machine file,
the first “functional” part of the file are the “in ports”. This section
specifies what <em>events</em> to <em>trigger</em> on different incoming messages.</p>

<p>However, before we get to the in ports, we must declare our out ports.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">out_port</span><span class="p">(</span><span class="n">request_out</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">,</span> <span class="n">requestToDir</span><span class="p">);</span>
<span class="n">out_port</span><span class="p">(</span><span class="n">response_out</span><span class="p">,</span> <span class="n">ResponseMsg</span><span class="p">,</span> <span class="n">responseToDirOrSibling</span><span class="p">);</span>
</code></pre></div></div>

<p>This code essentially just renames <code class="highlighter-rouge">requestToDir</code> and
<code class="highlighter-rouge">responseToDirOrSibling</code> to <code class="highlighter-rouge">request_out</code> and <code class="highlighter-rouge">response_out</code>. Later in
the file, when we want to <em>enqueue</em> messages to these message buffers we
will use the new names <code class="highlighter-rouge">request_out</code> and <code class="highlighter-rouge">response_out</code>. This also
specifies the exact implementation of the messages that we will send
across these ports. We will look at the exact definition of these types
below in the file <code class="highlighter-rouge">MSI-msg.sm</code>.</p>

<p>Next, we create an <em>in port code block</em>. In SLICC, there are many cases
where there are code blocks that look similar to <code class="highlighter-rouge">if</code> blocks, but they
encode specific information. For instance, the code inside an
<code class="highlighter-rouge">in_port()</code> block is put in a special generated file:
<code class="highlighter-rouge">L1Cache_Wakeup.cc</code>.</p>

<p>All of the <code class="highlighter-rouge">in_port</code> code blocks are executed in order (or based on the
priority if it is specified). On each active cycle for the controller,
the first <code class="highlighter-rouge">in_port</code> code is executed. If it is successful, it is
re-executed to see if there are other messages that can be consumed on
the port. If there are no messages or no events are triggered, then the
next <code class="highlighter-rouge">in_port</code> code block is executed.</p>

<p>There are three different kinds of <em>stalls</em> that can be generated when
executing <code class="highlighter-rouge">in_port</code> code blocks. First, there is a parameterized limit
for the number of transitions per cycle at each controller. If this
limit is reached (i.e., there are more messages on the message buffers
than the transition per cycle limit), then all <code class="highlighter-rouge">in_port</code> will stop
processing and wait to continue until the next cycle. Second, there
could be a <em>resource stall</em>. This happens if some needed resource is
unavailable. For instance, if using the <code class="highlighter-rouge">BankedArray</code> bandwidth model,
the needed bank of the cache may be currently occupied. Third, there
could be a <em>protocol stall</em>. This is a special kind of action that
causes the state machine to stall until the next cycle.</p>

<p>It is important to note that protocol stalls and resource stalls prevent
<strong>all</strong> <code class="highlighter-rouge">in_port</code> blocks from executing. For instance, if the first
<code class="highlighter-rouge">in_port</code> block generates a protocol stall, none of the other ports will
be executed, blocking all messages. This is why it is important to use
the correct number and ordering of virtual networks.</p>

<p>Below, is the full code for the <code class="highlighter-rouge">in_port</code> block for the highest priority
messages to our L1 cache controller, the response from directory or
other caches. Next we will break the code block down to explain each
section.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">in_port</span><span class="p">(</span><span class="n">response_in</span><span class="p">,</span> <span class="n">ResponseMsg</span><span class="p">,</span> <span class="n">responseFromDirOrSibling</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">response_in</span><span class="p">.</span><span class="n">isReady</span><span class="p">(</span><span class="n">clockEdge</span><span class="p">()))</span> <span class="p">{</span>
        <span class="n">peek</span><span class="p">(</span><span class="n">response_in</span><span class="p">,</span> <span class="n">ResponseMsg</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">Entry</span> <span class="n">cache_entry</span> <span class="o">:=</span> <span class="n">getCacheEntry</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">);</span>
            <span class="n">TBE</span> <span class="n">tbe</span> <span class="o">:=</span> <span class="n">TBEs</span><span class="p">[</span><span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">];</span>
            <span class="n">assert</span><span class="p">(</span><span class="n">is_valid</span><span class="p">(</span><span class="n">tbe</span><span class="p">));</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">machineIDToMachineType</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Sender</span><span class="p">)</span> <span class="o">==</span>
                        <span class="nl">MachineType:</span><span class="n">Directory</span><span class="p">)</span> <span class="p">{</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">!=</span> <span class="n">CoherenceResponseType</span><span class="o">:</span><span class="n">Data</span><span class="p">)</span> <span class="p">{</span>
                    <span class="n">error</span><span class="p">(</span><span class="s">"Directory should only reply with data"</span><span class="p">);</span>
                <span class="p">}</span>
                <span class="n">assert</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Acks</span> <span class="o">+</span> <span class="n">tbe</span><span class="p">.</span><span class="n">AcksOutstanding</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">);</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Acks</span> <span class="o">+</span> <span class="n">tbe</span><span class="p">.</span><span class="n">AcksOutstanding</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
                    <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">DataDirNoAcks</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span>
                            <span class="n">tbe</span><span class="p">);</span>
                <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                    <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">DataDirAcks</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span>
                            <span class="n">tbe</span><span class="p">);</span>
                <span class="p">}</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">CoherenceResponseType</span><span class="o">:</span><span class="n">Data</span><span class="p">)</span> <span class="p">{</span>
                    <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">DataOwner</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span>
                            <span class="n">tbe</span><span class="p">);</span>
                <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">CoherenceResponseType</span><span class="o">:</span><span class="n">InvAck</span><span class="p">)</span> <span class="p">{</span>
                    <span class="n">DPRINTF</span><span class="p">(</span><span class="n">RubySlicc</span><span class="p">,</span> <span class="s">"Got inv ack. %d left</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
                            <span class="n">tbe</span><span class="p">.</span><span class="n">AcksOutstanding</span><span class="p">);</span>
                    <span class="k">if</span> <span class="p">(</span><span class="n">tbe</span><span class="p">.</span><span class="n">AcksOutstanding</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
                        <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">LastInvAck</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span>
                                <span class="n">tbe</span><span class="p">);</span>
                    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                        <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">InvAck</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span>
                                <span class="n">tbe</span><span class="p">);</span>
                    <span class="p">}</span>
                <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                    <span class="n">error</span><span class="p">(</span><span class="s">"Unexpected response from other cache"</span><span class="p">);</span>
                <span class="p">}</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>First, like the out_port above “response_in” is the name we’ll use
later when we refer to this port, and “ResponseMsg” is the type of
message we expect on this port (since this port processes responses to
our requests). The first step in all <code class="highlighter-rouge">in_port</code> code blocks is to check
the message buffer to see if there are any messages to be processed. If
not, then this <code class="highlighter-rouge">in_port</code> code block is skipped and the next one is
executed.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">in_port</span><span class="p">(</span><span class="n">response_in</span><span class="p">,</span> <span class="n">ResponseMsg</span><span class="p">,</span> <span class="n">responseFromDirOrSibling</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">response_in</span><span class="p">.</span><span class="n">isReady</span><span class="p">(</span><span class="n">clockEdge</span><span class="p">()))</span> <span class="p">{</span>
        <span class="p">.</span> <span class="p">.</span> <span class="p">.</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Assuming there is a valid message in the message buffer, next, we grab
that message by using the special code block <code class="highlighter-rouge">peek</code>. Peek is a special
function. Any code inside a peek statement has a special variable
declared and populated: <code class="highlighter-rouge">in_msg</code>. This contains the message (of type
ResponseMsg in this case as specified by the second parameter of the
<code class="highlighter-rouge">peek</code> call) at the head of the port. Here, <code class="highlighter-rouge">response_in</code> is the port we
want to peek into.</p>

<p>Then, we need to grab the cache entry and the TBE for the incoming
address. (We will look at the other parameters in response message
below.) Above, we implemented getCacheEntry. It will return either the
valid matching entry for the address, or an invalid entry if there is
not a matching cache block.</p>

<p>For the TBE, since this is a response to a request this cache controller
initiated, there <em>must</em> be a valid TBE in the TBE table. Hence, we see
our first debug statement, an <em>assert</em>. This is one of the ways to ease
debugging of cache coherence protocols. It is encouraged to use asserts
liberally to make debugging easier.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">peek</span><span class="p">(</span><span class="n">response_in</span><span class="p">,</span> <span class="n">ResponseMsg</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">Entry</span> <span class="n">cache_entry</span> <span class="o">:=</span> <span class="n">getCacheEntry</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">);</span>
    <span class="n">TBE</span> <span class="n">tbe</span> <span class="o">:=</span> <span class="n">TBEs</span><span class="p">[</span><span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">];</span>
    <span class="n">assert</span><span class="p">(</span><span class="n">is_valid</span><span class="p">(</span><span class="n">tbe</span><span class="p">));</span>

    <span class="p">.</span> <span class="p">.</span> <span class="p">.</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Next, we need to decide what event to trigger based on the message. For
this, we first need to discuss what data response messages are carrying.</p>

<p>To declare a new message type, first create a new file for all of the
message types: <code class="highlighter-rouge">MSI-msg.sm</code>. In this file, you can declare any
structures that will be <em>globally</em> used across all of the SLICC files
for your protocol. We will include this file in all of the state machine
definitions via the <code class="highlighter-rouge">MSI.slicc</code> file later. This is similar to including
global definitions in header files in C/C++.</p>

<p>In the <code class="highlighter-rouge">MSI-msg.sm</code> file, add the following code block:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">structure</span><span class="p">(</span><span class="n">ResponseMsg</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Used for Dir-&gt;Cache and Fwd message responses"</span><span class="p">,</span>
          <span class="n">interface</span><span class="o">=</span><span class="s">"Message"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">Addr</span> <span class="n">addr</span><span class="p">,</span>                   <span class="n">desc</span><span class="o">=</span><span class="s">"Physical address for this response"</span><span class="p">;</span>
    <span class="n">CoherenceResponseType</span> <span class="n">Type</span><span class="p">,</span>  <span class="n">desc</span><span class="o">=</span><span class="s">"Type of response"</span><span class="p">;</span>
    <span class="n">MachineID</span> <span class="n">Sender</span><span class="p">,</span>            <span class="n">desc</span><span class="o">=</span><span class="s">"Node who is responding to the request"</span><span class="p">;</span>
    <span class="n">NetDest</span> <span class="n">Destination</span><span class="p">,</span>         <span class="n">desc</span><span class="o">=</span><span class="s">"Multicast destination mask"</span><span class="p">;</span>
    <span class="n">DataBlock</span> <span class="n">DataBlk</span><span class="p">,</span>           <span class="n">desc</span><span class="o">=</span><span class="s">"data for the cache line"</span><span class="p">;</span>
    <span class="n">MessageSizeType</span> <span class="n">MessageSize</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"size category of the message"</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">Acks</span><span class="p">,</span>                    <span class="n">desc</span><span class="o">=</span><span class="s">"Number of acks required from others"</span><span class="p">;</span>

    <span class="c1">// This must be overridden here to support functional accesses</span>
    <span class="kt">bool</span> <span class="n">functionalRead</span><span class="p">(</span><span class="n">Packet</span> <span class="o">*</span><span class="n">pkt</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">Type</span> <span class="o">==</span> <span class="n">CoherenceResponseType</span><span class="o">:</span><span class="n">Data</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">return</span> <span class="n">testAndRead</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="n">DataBlk</span><span class="p">,</span> <span class="n">pkt</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kt">bool</span> <span class="n">functionalWrite</span><span class="p">(</span><span class="n">Packet</span> <span class="o">*</span><span class="n">pkt</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// No check on message type required since the protocol should read</span>
        <span class="c1">// data block from only those messages that contain valid data</span>
        <span class="k">return</span> <span class="n">testAndWrite</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="n">DataBlk</span><span class="p">,</span> <span class="n">pkt</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The message is just another SLICC structure similar to the structures
we’ve defined before. However, this time, we have a specific interface
that it is implementing: <code class="highlighter-rouge">Message</code>. Within this message, we can add any
members that we need for our protocol. In this case, we first have the
address. Note, a common “gotcha” is that you <em>cannot</em> use “Addr” with a
capitol “A” for the name of the member since it is the same name as the
type!</p>

<p>Next, we have the type of response. In our case, there are two types of
response data and invalidation acks from other caches after they have
invalidated their copy. Thus, we need to define an <em>enumeration</em>, the
<code class="highlighter-rouge">CoherenceResponseType</code>, to use it in this message. Add the following
code <em>before</em> the <code class="highlighter-rouge">ResponseMsg</code> declaration in the same file.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">enumeration</span><span class="p">(</span><span class="n">CoherenceResponseType</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Types of response messages"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">Data</span><span class="p">,</span>       <span class="n">desc</span><span class="o">=</span><span class="s">"Contains the most up-to-date data"</span><span class="p">;</span>
    <span class="n">InvAck</span><span class="p">,</span>     <span class="n">desc</span><span class="o">=</span><span class="s">"Message from another cache that they have inv. the blk"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Next, in the response message type, we have the <code class="highlighter-rouge">MachineID</code> which sent
the response. <code class="highlighter-rouge">MachineID</code> is the <em>specific machine</em> that sent the
response. For instance, it might be directory 0 or cache 12. The
<code class="highlighter-rouge">MachineID</code> contains both the <code class="highlighter-rouge">MachineType</code> (e.g., we have been creating
an <code class="highlighter-rouge">L1Cache</code> as declared in the first <code class="highlighter-rouge">machine()</code>) and the specific
<em>version</em> of that machine type. We will come back to machine version
numbers when configuring the system.</p>

<p>Next, all messages need a <em>destination</em>, and a <em>size</em>. The destination
is specified as a <code class="highlighter-rouge">NetDest</code>, which is a bitmap of all the <code class="highlighter-rouge">MachineID</code> in
the system. This allows messages to be broadcast to a flexible set of
receivers. The message also has a size. You can find the possible
message sizes in <code class="highlighter-rouge">src/mem/protocol/RubySlicc_Exports.sm</code>.</p>

<p>This message may also contain a data block and the number acks that are
expected. Thus, we can include these in the message definition as well.</p>

<p>Finally, we also have to define functional read and write functions.
These are used by Ruby to inspect in-flight messages on function reads
and writes. Note: This functionality currently is very brittle and if
there are messages in-flight for an address that is functionally read or
written the functional access may fail.</p>

<p>You can download the complete <code class="highlighter-rouge">MSI-msg.sm</code> file 
<a href="/_pages/static/scripts/part3/MSI_protocol/MSI-msg.sm">here</a>.</p>

<p>Now that we have defined the data in the response message, we can look
at how we choose which action to trigger in the <code class="highlighter-rouge">in_port</code> for response
to the cache.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// If it's from the directory...</span>
<span class="k">if</span> <span class="p">(</span><span class="n">machineIDToMachineType</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Sender</span><span class="p">)</span> <span class="o">==</span>
            <span class="n">MachineType</span><span class="o">:</span><span class="n">Directory</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">!=</span> <span class="n">CoherenceResponseType</span><span class="o">:</span><span class="n">Data</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">error</span><span class="p">(</span><span class="s">"Directory should only reply with data"</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="n">assert</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Acks</span> <span class="o">+</span> <span class="n">tbe</span><span class="p">.</span><span class="n">AcksOutstanding</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Acks</span> <span class="o">+</span> <span class="n">tbe</span><span class="p">.</span><span class="n">AcksOutstanding</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">DataDirNoAcks</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span>
                <span class="n">tbe</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">DataDirAcks</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span>
                <span class="n">tbe</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="c1">// This is from another cache.</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">CoherenceResponseType</span><span class="o">:</span><span class="n">Data</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">DataOwner</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span>
                <span class="n">tbe</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">CoherenceResponseType</span><span class="o">:</span><span class="n">InvAck</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">DPRINTF</span><span class="p">(</span><span class="n">RubySlicc</span><span class="p">,</span> <span class="s">"Got inv ack. %d left</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
                <span class="n">tbe</span><span class="p">.</span><span class="n">AcksOutstanding</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">tbe</span><span class="p">.</span><span class="n">AcksOutstanding</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
            <span class="c1">// If there is exactly one ack remaining then we</span>
            <span class="c1">// know it is the last ack.</span>
            <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">LastInvAck</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span>
                    <span class="n">tbe</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">InvAck</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span>
                    <span class="n">tbe</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">error</span><span class="p">(</span><span class="s">"Unexpected response from other cache"</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>First, we check to see if the message comes from the directory or
another cache. If it comes from the directory, we know that it <em>must</em> be
a data response (the directory will never respond with an ack).</p>

<p>Here, we meet our second way to add debug information to protocols: the
<code class="highlighter-rouge">error</code> function. This function breaks simulation and prints out the
string parameter similar to <code class="highlighter-rouge">panic</code>.</p>

<p>Next, when we receive data from the directory, we expect that the number
of acks we are waiting for will never be less than 0. The number of acks
we’re waiting for is the current acks we have received
(tbe.AcksOutstanding) and the number of acks the directory has told us
to be waiting for. We need to check it this way because it is possible
that we have received acks from other caches before we get the message
from the directory that we need to wait for acks.</p>

<p>There are two possibilities for the acks, either we have already
received all of the acks and now we are getting the data (data from dir
acks==0 in Table 8.3), or we need to wait for more acks. Thus, we check
this condition and trigger two different events, one for each
possibility.</p>

<p>When triggering transitions, you need to pass four parameters. The first
parameter is the event to trigger. These events were specified earlier
in the <code class="highlighter-rouge">Event</code> declaration. The next parameter is the (physical memory)
address of the cache block to operate on. Usually this is the same as
the address of the <code class="highlighter-rouge">in_msg</code>, but it may be different, for instance, on a
replacement the address is for the block being replaced. Next is the
cache entry and the TBE for the block. These may be invalid if there are
no valid entries for the address in the cache or there is not a valid
TBE in the TBE table.</p>

<p>When we implement actions below, we will see how these last three
parameters are used. They are passed into the actions as implicit
variables: <code class="highlighter-rouge">address</code>, <code class="highlighter-rouge">cache_entry</code>, and <code class="highlighter-rouge">tbe</code>.</p>

<p>If the <code class="highlighter-rouge">trigger</code> function is executed, after the transition is complete,
the <code class="highlighter-rouge">in_port</code> logic is executed again, assuming there have been fewer
transitions than that maximum transitions per cycle. If there are other
messages in the message buffer more transitions can be triggered.</p>

<p>If the response is from another cache instead of the directory, then
other events are triggered, as shown in the code above. These events
come directly from Table 8.3 in Sorin et al.</p>

<p>Importantly, you should use the <code class="highlighter-rouge">in_port</code> logic to check all conditions.
After an event is triggered, it should only have a <em>single code path</em>.
I.e., there should be no <code class="highlighter-rouge">if</code> statements in any action blocks. If you
want to conditionally execute actions, you should use different states
or different events in the <code class="highlighter-rouge">in_port</code> logic.</p>

<p>The reason for this constraint is the way Ruby checks resources before
executing a transition. In the generated code from the <code class="highlighter-rouge">in_port</code> blocks
before the transition is actually executed all of the resources are
checked. In other words, transitions are atomic and either execute all
of the actions or none. Conditional statements inside the actions
prevents the SLICC compiler from correctly tracking the resource usage
and can lead to strange performance, deadlocks, and other bugs.</p>

<p>After specifying the <code class="highlighter-rouge">in_port</code> logic for the highest priority network,
the response network, we need to add the <code class="highlighter-rouge">in_port</code> logic for the forward
request network. However, before specifying this logic, we need to
define the <code class="highlighter-rouge">RequestMsg</code> type and the <code class="highlighter-rouge">CoherenceRequestType</code> which
contains the types of requests. These two definitions go in the
<code class="highlighter-rouge">MSI-msg.sm</code> file <em>not in MSI-cache.sm</em> since they are global
definitions.</p>

<p>It is possible to implement this as two different messages and request
type enumerations, one for forward and one for normal requests, but it
simplifies the code to use a single message and type.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">enumeration</span><span class="p">(</span><span class="n">CoherenceRequestType</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Types of request messages"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">GetS</span><span class="p">,</span>       <span class="n">desc</span><span class="o">=</span><span class="s">"Request from cache for a block with read permission"</span><span class="p">;</span>
    <span class="n">GetM</span><span class="p">,</span>       <span class="n">desc</span><span class="o">=</span><span class="s">"Request from cache for a block with write permission"</span><span class="p">;</span>
    <span class="n">PutS</span><span class="p">,</span>       <span class="n">desc</span><span class="o">=</span><span class="s">"Sent to directory when evicting a block in S (clean WB)"</span><span class="p">;</span>
    <span class="n">PutM</span><span class="p">,</span>       <span class="n">desc</span><span class="o">=</span><span class="s">"Sent to directory when evicting a block in M"</span><span class="p">;</span>

    <span class="c1">// "Requests" from the directory to the caches on the fwd network</span>
    <span class="n">Inv</span><span class="p">,</span>        <span class="n">desc</span><span class="o">=</span><span class="s">"Probe the cache and invalidate any matching blocks"</span><span class="p">;</span>
    <span class="n">PutAck</span><span class="p">,</span>     <span class="n">desc</span><span class="o">=</span><span class="s">"The put request has been processed."</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">structure</span><span class="p">(</span><span class="n">RequestMsg</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Used for Cache-&gt;Dir and Fwd messages"</span><span class="p">,</span>  <span class="n">interface</span><span class="o">=</span><span class="s">"Message"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">Addr</span> <span class="n">addr</span><span class="p">,</span>                   <span class="n">desc</span><span class="o">=</span><span class="s">"Physical address for this request"</span><span class="p">;</span>
    <span class="n">CoherenceRequestType</span> <span class="n">Type</span><span class="p">,</span>   <span class="n">desc</span><span class="o">=</span><span class="s">"Type of request"</span><span class="p">;</span>
    <span class="n">MachineID</span> <span class="n">Requestor</span><span class="p">,</span>         <span class="n">desc</span><span class="o">=</span><span class="s">"Node who initiated the request"</span><span class="p">;</span>
    <span class="n">NetDest</span> <span class="n">Destination</span><span class="p">,</span>         <span class="n">desc</span><span class="o">=</span><span class="s">"Multicast destination mask"</span><span class="p">;</span>
    <span class="n">DataBlock</span> <span class="n">DataBlk</span><span class="p">,</span>           <span class="n">desc</span><span class="o">=</span><span class="s">"data for the cache line"</span><span class="p">;</span>
    <span class="n">MessageSizeType</span> <span class="n">MessageSize</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"size category of the message"</span><span class="p">;</span>

    <span class="kt">bool</span> <span class="n">functionalRead</span><span class="p">(</span><span class="n">Packet</span> <span class="o">*</span><span class="n">pkt</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// Requests should never have the only copy of the most up-to-date data</span>
        <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kt">bool</span> <span class="n">functionalWrite</span><span class="p">(</span><span class="n">Packet</span> <span class="o">*</span><span class="n">pkt</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// No check on message type required since the protocol should read</span>
        <span class="c1">// data block from only those messages that contain valid data</span>
        <span class="k">return</span> <span class="n">testAndWrite</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="n">DataBlk</span><span class="p">,</span> <span class="n">pkt</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Now, we can specify the logic for the forward network <code class="highlighter-rouge">in_port</code>. This
logic is straightforward and triggers a different event for each request
type.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">in_port</span><span class="p">(</span><span class="n">forward_in</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">,</span> <span class="n">forwardFromDir</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">forward_in</span><span class="p">.</span><span class="n">isReady</span><span class="p">(</span><span class="n">clockEdge</span><span class="p">()))</span> <span class="p">{</span>
        <span class="n">peek</span><span class="p">(</span><span class="n">forward_in</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">)</span> <span class="p">{</span>
            <span class="c1">// Grab the entry and tbe if they exist.</span>
            <span class="n">Entry</span> <span class="n">cache_entry</span> <span class="o">:=</span> <span class="n">getCacheEntry</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">);</span>
            <span class="n">TBE</span> <span class="n">tbe</span> <span class="o">:=</span> <span class="n">TBEs</span><span class="p">[</span><span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">];</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">CoherenceRequestType</span><span class="o">:</span><span class="n">GetS</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">FwdGetS</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span> <span class="n">tbe</span><span class="p">);</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">CoherenceRequestType</span><span class="o">:</span><span class="n">GetM</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">FwdGetM</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span> <span class="n">tbe</span><span class="p">);</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">CoherenceRequestType</span><span class="o">:</span><span class="n">Inv</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">Inv</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span> <span class="n">tbe</span><span class="p">);</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">CoherenceRequestType</span><span class="o">:</span><span class="n">PutAck</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">PutAck</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span> <span class="n">tbe</span><span class="p">);</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="n">error</span><span class="p">(</span><span class="s">"Unexpected forward message!"</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The final <code class="highlighter-rouge">in_port</code> is for the mandatory queue. This is the lowest
priority queue, so it must be lowest in the state machine file. The
mandatory queue has a special message type: <code class="highlighter-rouge">RubyRequest</code>. This type is
specified in <code class="highlighter-rouge">src/mem/protocol/RubySlicc_Types.sm</code> It contains two
different addresses, the <code class="highlighter-rouge">LineAddress</code> which is cache-block aligned and
the <code class="highlighter-rouge">PhysicalAddress</code> which holds the original request’s address and may
not be cache-block aligned. It also has other members that may be useful
in some protocols. However, for this simple protocol we only need the
<code class="highlighter-rouge">LineAddress</code>.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">in_port</span><span class="p">(</span><span class="n">mandatory_in</span><span class="p">,</span> <span class="n">RubyRequest</span><span class="p">,</span> <span class="n">mandatoryQueue</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">mandatory_in</span><span class="p">.</span><span class="n">isReady</span><span class="p">(</span><span class="n">clockEdge</span><span class="p">()))</span> <span class="p">{</span>
        <span class="n">peek</span><span class="p">(</span><span class="n">mandatory_in</span><span class="p">,</span> <span class="n">RubyRequest</span><span class="p">,</span> <span class="n">block_on</span><span class="o">=</span><span class="s">"LineAddress"</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">Entry</span> <span class="n">cache_entry</span> <span class="o">:=</span> <span class="n">getCacheEntry</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">LineAddress</span><span class="p">);</span>
            <span class="n">TBE</span> <span class="n">tbe</span> <span class="o">:=</span> <span class="n">TBEs</span><span class="p">[</span><span class="n">in_msg</span><span class="p">.</span><span class="n">LineAddress</span><span class="p">];</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">is_invalid</span><span class="p">(</span><span class="n">cache_entry</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
                    <span class="n">cacheMemory</span><span class="p">.</span><span class="n">cacheAvail</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">LineAddress</span><span class="p">)</span> <span class="o">==</span> <span class="nb">false</span> <span class="p">)</span> <span class="p">{</span>
                <span class="n">Addr</span> <span class="n">addr</span> <span class="o">:=</span> <span class="n">cacheMemory</span><span class="p">.</span><span class="n">cacheProbe</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">LineAddress</span><span class="p">);</span>
                <span class="n">Entry</span> <span class="n">victim_entry</span> <span class="o">:=</span> <span class="n">getCacheEntry</span><span class="p">(</span><span class="n">addr</span><span class="p">);</span>
                <span class="n">TBE</span> <span class="n">victim_tbe</span> <span class="o">:=</span> <span class="n">TBEs</span><span class="p">[</span><span class="n">addr</span><span class="p">];</span>
                <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">Replacement</span><span class="p">,</span> <span class="n">addr</span><span class="p">,</span> <span class="n">victim_entry</span><span class="p">,</span> <span class="n">victim_tbe</span><span class="p">);</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">RubyRequestType</span><span class="o">:</span><span class="n">LD</span> <span class="o">||</span>
                        <span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">RubyRequestType</span><span class="o">:</span><span class="n">IFETCH</span><span class="p">)</span> <span class="p">{</span>
                    <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">Load</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">LineAddress</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span>
                            <span class="n">tbe</span><span class="p">);</span>
                <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">RubyRequestType</span><span class="o">:</span><span class="n">ST</span><span class="p">)</span> <span class="p">{</span>
                    <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">Store</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">LineAddress</span><span class="p">,</span> <span class="n">cache_entry</span><span class="p">,</span>
                            <span class="n">tbe</span><span class="p">);</span>
                <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                    <span class="n">error</span><span class="p">(</span><span class="s">"Unexpected type from processor"</span><span class="p">);</span>
                <span class="p">}</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>There are a couple of new concepts shown in this code block. First, we
use <code class="highlighter-rouge">block_on="LineAddress"</code> in the peek function. What this does is
ensure that any other requests to the same cache line will be blocked
until the current request is complete.</p>

<p>Next, we check if the cache entry for this line is valid. If not, and
there are no more entries available in the set, then we need to evict
another entry. To get the victim address, we can use the <code class="highlighter-rouge">cacheProbe</code>
function on the <code class="highlighter-rouge">CacheMemory</code> object. This function uses the
parameterized replacement policy and returns the physical (line) address
of the victim.</p>

<p>Importantly, when we trigger the <code class="highlighter-rouge">Replacement</code> event <em>we use the address
of the victim block</em> and the victim cache entry and tbe. Thus, when we
take actions in the replacement transitions we will be acting on the
victim block, not the requesting block. Additionally, we need to
remember to <em>not</em> remove the requesting message from the mandatory queue
(pop) until it has been satisfied. The message should not be popped
after the replacement is complete.</p>

<p>If the cache block was found to be valid, then we simply trigger the
<code class="highlighter-rouge">Load</code> or <code class="highlighter-rouge">Store</code> event.</p>

  <br>

  <!-- RETRIVE PREVIOUS PAGE LINK -->
  
    
  
    
  
    
  
    
  

  <!-- RETRIEVE NEXT PAGE LINK -->
  
    
  
    
  
    
  
    
  


  <div class="navbuttons">
    
      <a href=""><button type="button" class="btn btn-outline-primary">PREVIOUS</button></a>
    

    
      <a href=""><button type="button" class="btn btn-outline-primary">NEXT</button></a>
    
  </div>
</div>

	</main>
	<footer class="page-footer">
	<div class="container">
		<div class="row">

			<div class="col-12 col-sm-4">
				<p>gem5</p>
				<p><a href="/about">About</a></p>
				<p><a href="/publications">Publications</a></p>
				<p><a href="/contributing">Contributing</a></p>
				<p><a href="/governance">Governance</a></p>
			<br></div>

			<div class="col-12 col-sm-4">
				<p>Docs</p>
				<p><a href="/documentation">Documentation</a></p>
				<p><a href="http://gem5.org/Documentation">Old Documentation</a></p>
				<p><a href="https://gem5.googlesource.com/public/gem5">Source</a></p>
			<br></div>

			<div class="col-12 col-sm-4">
				<p>Help</p>
				<p><a href="/search">Search</a></p>
				<p><a href="/mailing_lists">Mailing Lists</a></p>
				<p><a href="https://gem5.googlesource.com/public/gem5-website/+/refs/heads/master/README.md">Website Source</a></p>
			<br></div>

		</div>
	</div>
</footer>


	<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
	<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
	<script src="https://unpkg.com/commentbox.io/dist/commentBox.min.js"></script>

	<script>
	  // When the user scrolls down 20px from the top of the document, show the button
	  window.onscroll = function() {scrollFunction()};

	  function scrollFunction() {
	      if (document.body.scrollTop > 100 || document.documentElement.scrollTop > 20) {
	          document.getElementById("myBtn").style.display = "block";
	      } else {
	          document.getElementById("myBtn").style.display = "none";
	      }
	  }

	  // When the user clicks on the button, scroll to the top of the document
	  function topFunction() {
	      document.body.scrollTop = 0;
	      document.documentElement.scrollTop = 0;
	  }

		import commentBox from 'commentbox.io';
		// or
		const commentBox = require('commentbox.io');
		// or if using the CDN, it will be available as a global "commentBox" variable.

		commentBox('my-project-id');

	</script>

</body>


</html>
